package com.fingard.dsp.bank.directbank.abc23.util;

import java.io.*;
import java.util.zip.*;

/**
 * 压缩帮助类
 * @author Administrator
 *
 */
public class ZipHelper {
	private static final int BUFFER_SIZE = 1024;
	private static final String PATH_SEP = "/";
	/**
	 * 
	 * @param sourceFileName
	 * @param destFileName
	 * @throws IOException
	 */
	public static void zipCompress(String sourceFileName, String destFileName) throws IOException
	{
		File sourceFile = new File(sourceFileName);
		File destFile = new File(destFileName);
		zipCompress(sourceFile, destFile);
	}
	/**
	 * 
	 * @param sourceFile
	 * @param destFile
	 * @throws IOException
	 */
	public static void zipCompress(File sourceFile, File destFile) throws IOException
	{
		FileOutputStream fos = null;
		CheckedOutputStream cos = null;
		ZipOutputStream zos = null;
		try
		{
			fos = new FileOutputStream(destFile);
			cos = new CheckedOutputStream(fos, new CRC32());
			zos = new ZipOutputStream(cos);
			zipCompress(sourceFile, zos, "");
			zos.flush();
			zos.finish();
		}
		finally
		{
			//这里内部会调用 cos, fos 的 close 方法
			if(zos != null)
				zos.close();
			if(cos != null)
				cos.close();
			if(fos != null)
				fos.close();
		}
	}
	/**
	 * 
	 * @param sourceFile
	 * @param zos
	 * @param basePath
	 * @throws IOException
	 */
	private static void zipCompress(File sourceFile, ZipOutputStream zos, String basePath) throws IOException
	{
		if(sourceFile.isDirectory())
			zipCompressDir(sourceFile, zos, basePath);
		else 
			zipCompressFile(sourceFile, zos, basePath);
	}
	/**
	 * 对文件夹进行压缩，到输出流
	 * @param dir 文件夹
	 * @param zos 输出流
	 * @param basePath 压缩文件中的相对路径
	 * @throws IOException 
	 */
	private static void zipCompressDir(File dir, ZipOutputStream zos, String basePath) throws IOException
	{
		File[] files = dir.listFiles();
		String newBasePath = basePath + dir.getName() + PATH_SEP;
		//构建空目录
		if(files.length <= 0)
		{
			ZipEntry entry = new ZipEntry(newBasePath);
			zos.putNextEntry(entry);
			zos.closeEntry();
		}
		//递归压缩
		for(File file : files)
		{
			zipCompress(file, zos, newBasePath);
		}
	}
	/**
	 * 对文件进行压缩，到输出流
	 * @param file 待压缩文件
	 * @param zos 输出流
	 * @param basePath 压缩文件中的相对路径
	 * @throws IOException 
	 */
	private static void zipCompressFile(File file, ZipOutputStream zos, String basePath) throws IOException
	{
		String entryName = basePath + file.getName();
		FileInputStream fis = new FileInputStream(file);
		zipCompress(fis, zos, entryName);
	}

	/**
	 * 将数据压缩
	 * @param sourceBytes 原始数据
	 * @param entryName 用来保存原始文件名
	 * @throws IOException 
	 */
	public static byte[] zipCompress(InputStream is, String entryName) throws IOException
	{
		ByteArrayOutputStream baos = null;
		CheckedOutputStream cos = null;
		ZipOutputStream zos = null;
		try
		{
			baos = new ByteArrayOutputStream();
			cos = new CheckedOutputStream(baos, new CRC32());
			zos = new ZipOutputStream(cos);
			
			zos.setMethod(ZipOutputStream.DEFLATED);
			zipCompress(is,zos,entryName);
			zos.flush();
			zos.finish();
			byte[] result = baos.toByteArray();
			return result;
		}
		finally
		{
			if(zos != null)
				zos.close();
			if(cos != null)
				cos.close();
			if(baos != null)
				baos.close();
		}
	}
	/**
	 * 将输入流的数据压缩，到输出流
	 * @param is 待压缩的流
	 * @param zos 压缩后的输出流
	 * @param entryName 原始文件名
	 * @throws IOException 
	 */
	private static void zipCompress(InputStream is, ZipOutputStream zos, String entryName) throws IOException
	{
		BufferedInputStream bis = null;
		try
		{
			bis = new BufferedInputStream(is);
			ZipEntry entry = new ZipEntry(entryName);
			zos.putNextEntry(entry);
			int count;
			byte[] buffer = new byte[BUFFER_SIZE];
			while(true)
			{
				count = bis.read(buffer, 0, BUFFER_SIZE);
				if(count < 0)
					break;
				zos.write(buffer, 0, count);
			}
			zos.closeEntry();
		}
		finally
		{
			if(bis != null)
				bis.close();
		}
	}

	/**
	 * 将压缩文件解压缩到目标文件夹
	 * @param sourceFileName
	 * @param destFileName
	 * @throws IOException 
	 */
	public static void zipDecompress(String sourceFileName, String destDir) throws IOException
	{
		zipDecompress(new File(sourceFileName), new File(destDir));
	}
	/**
	 * 将压缩文件解压缩到目标文件夹
	 * @param sourceFile
	 * @param destFile
	 * @throws IOException 
	 */
	public static void zipDecompress(File sourceFile, File destDir) throws IOException
	{
		FileInputStream fis = null;
		try
		{
			fis = new FileInputStream(sourceFile);
			zipDecompress(fis, destDir);
		}
		finally
		{
			if(fis != null)
				fis.close();
		}
	}
	/**
	 * 将数据中的内容解压缩到目标文件夹
	 * @param sourceBytes
	 * @param destDir
	 * @throws IOException 
	 */
	public static void zipDecompress(byte[] sourceBytes, File destDir) throws IOException
	{
		ByteArrayInputStream bais = null;
		try
		{
			bais = new ByteArrayInputStream(sourceBytes);
			zipDecompress(bais, destDir);
		}
		finally
		{
			if(bais != null)
				bais.close();
		}
	}
	/**
	 * 将流中的内容解压缩到目标文件夹
	 * @param is
	 * @param destFile
	 * @throws IOException 
	 */
	public static void zipDecompress(InputStream is, File destFile) throws IOException
	{
		CheckedInputStream cis = null;
		ZipInputStream zis = null;
		try
		{
			cis = new CheckedInputStream(is, new CRC32());
			zis = new ZipInputStream(cis);
			zipDecompress(zis, destFile);
		}
		finally
		{
			if(zis != null)
				zis.close();
			if(cis != null)
				cis.close();
		}
	}
	/**
	 * 使用 ZipInputStream 进行解压缩操作，解压缩到目标文件夹
	 * @param zis
	 * @param destFile
	 * @throws IOException 
	 */
	private static void zipDecompress(ZipInputStream zis, File destFile) throws IOException
	{
		while(true)
		{
			ZipEntry entry = zis.getNextEntry();
			if(entry == null)
				break;
			String dir = destFile.getPath() + File.separator + entry.getName();
			File dirFile = new File(dir);
			IOHelper.ensureFolderExists(dirFile);
			
			//如果当前 Entry 是目录而不是文件，则创建目录。
			if(entry.isDirectory())
			{
				dirFile.mkdir();
			}
			//如果当前 Entry 是文件，则将解压缩内容生成文件。
			else
			{
				zipDecompressFile(zis, dirFile);
			}
			zis.closeEntry();
		}
	}
	/**
	 * 将压缩流中当前 Entry 的内容解压缩到指定文件。
	 * 这里需要确保当前的 Entry 是文件而不是目录。
	 * @param zis
	 * @param destFile
	 * @throws IOException 
	 */
	private static void zipDecompressFile(ZipInputStream zis, File destFile) throws IOException
	{
		BufferedOutputStream bos = null;
		int count;
		try
		{
			bos = new BufferedOutputStream(new FileOutputStream(destFile));
			byte[] buffer = new byte[BUFFER_SIZE];
			while(true)
			{
				count = zis.read(buffer, 0, BUFFER_SIZE);
				if(count < 0)
					break;
				bos.write(buffer, 0, count);
			}
		}
		finally
		{
			if(bos != null)
				bos.close();
		}
	}
	/**
	 * 将压缩文件解压缩为单个指定文件名的文件，而不使用文件的原始文件名。
	 * 这种方式压缩文件中必须而且只能包含 1 个文件。
	 * @param sourceFileName
	 * @param destFileName
	 * @throws IOException 
	 */
	public static void zipDecompressAsSingleFile(String sourceFileName, String destFileName) throws IOException
	{
		CheckedInputStream cis = null;
		ZipInputStream zis = null;
		FileInputStream fis = null;
		try
		{
		    fis = new FileInputStream(new File(sourceFileName));
			cis = new CheckedInputStream(fis, new CRC32());
			zis = new ZipInputStream(cis);
			//这里有可能会没有 Entry?
			zis.getNextEntry();
			zipDecompressFile(zis, new File(destFileName));
		}
		finally
		{
			if(zis != null)
				zis.close();
			if(cis != null)
				cis.close();
            if(fis != null)
                fis.close();
		}
	}
}











